<template>
  <div class="containner">
    <div v-if="startChat" ref="conversationRef" class="conversation-area">
      <template v-for="(msg, idx) in messages" :key="idx">
        <McBubble v-if="msg.from === 'user'" :align="'right'">
          <McMarkdownCard :content="msg.content" :theme="theme"></McMarkdownCard>
        </McBubble>
        <template v-else>
          <div v-if="msg.loading && !msg.isStop" class="hp-badge hp-badge-primary">
            <Loader2 :size="14" class="hp-icon-sm hp-spin" />
            <span>正在回答</span>
          </div>
           <div v-else>
            <div v-if="msg.isStop" class="hp-badge hp-badge-warning">
              <AlertCircle :size="14" class="hp-icon-sm" />
              <span>暂停回答</span>
            </div>
            <div v-else class="hp-badge hp-badge-success">
              <CheckCheck :size="14" class="hp-icon-sm" />
              <span>完成回答</span>
            </div>
          </div>
          <McBubble>
            <McMarkdownCard :content="msg.content" :theme="theme">
              <template #header="{ codeBlockData }">
                <div class="header-container">
                  <div class="header-left">
                  </div>
                  <div class="header-right">
                    <d-tooltip position="left" content="插入">
                      <i class="icon-insert" @click="insertCodeAtCursor(codeBlockData)"></i>
                    </d-tooltip>
                    <d-tooltip position="left" content="复制">
                      <i class="icon-copy-new" @click="copyText(codeBlockData)"></i>
                    </d-tooltip>
                  </div>
                </div>
              </template>
            </McMarkdownCard>
            <!-- 文件信息（只读，只有查看按钮） -->
            <div v-if="msg.fileInfo" class="file-info-container hp-card hp-fade-in">
              <div class="file-info-path">{{ msg.fileInfo.displayPath }}</div>
              <div class="file-info-buttons">
                <button class="hp-button hp-button-primary hp-button-sm" @click="openFile(msg.fileInfo.filePath)">
                  <FolderOpen :size="16" class="hp-icon-sm" />
                  <span>查看文件</span>
                </button>
              </div>
            </div>
            <!-- 文件操作按钮 -->
            <div v-if="msg.fileAction && !msg.fileAction.decided" class="file-action-container hp-card hp-slide-up">
              <div class="file-action-path">{{ msg.fileAction.displayPath }}</div>
              <div class="file-action-buttons">
                <button class="hp-button hp-button-secondary hp-button-sm" @click="openFile(msg.fileAction.filePath)">
                  <FolderOpen :size="16" class="hp-icon-sm" />
                  <span>查看文件</span>
                </button>
                <button class="hp-button hp-button-success hp-button-sm" @click="handleFileActionResponse(msg.fileAction.actionId, 'accept')">
                  <CheckCircle2 :size="16" class="hp-icon-sm" />
                  <span>采纳</span>
                </button>
                <button class="hp-button hp-button-warning hp-button-sm" @click="handleFileActionResponse(msg.fileAction.actionId, 'reject')">
                  <XCircle :size="16" class="hp-icon-sm" />
                  <span>拒绝</span>
                </button>
              </div>
            </div>
          </McBubble>
        </template>
      </template>
    </div>
    <div v-else class="welcome-page">
              <McIntroduction :logo-img="logo2Png" title="HarmonyPilot" sub-title="Hi，欢迎使用 HarmonyPilot" :description="[
          'HarmonyPilot（鸿蒙领航员，简称\'鸿派\'）。',
          '是一个为鸿蒙开发者提供沉浸式AI使用体验的服务或者工具，',
          '提供代码生成、智能问答、测试辅助、代码检测等功能。',
          '并通过智能Agent，在应用、外设驱动、设备开发等领域，',
          '提供自主编排、工程生成、智能调测等能力，提升开发者的体验和效率。',
      ]" class="headerIcon2x"></McIntroduction>
    </div>
    <div class="new-convo-button">
      <div class="agent-knowledge">
        <d-dropdown :position="['top']" @toggle="(val) => (isAgentOpen = val)">
          <div class="agent-wrapper">
            <img :src="logoPng" />
            <span>{{ selectedAgent.label }}</span>
            <i class="icon-infrastructure"></i>
            <i :class="['icon-chevron-down-2', { 'is-open': isAgentOpen }]"></i>
          </div>
        </d-dropdown>
      </div>
      <!-- UT 生成控制按钮 -->
      <template v-if="isGeneratingUT">
        <!-- 🔍 调试：在控制台输出渲染信息 -->
        <span style="display: none;">{{ console.log('[AiChat] 🎨 正在渲染 UT 按钮, isGeneratingUT =', isGeneratingUT, ', isUTPaused =', isUTPaused) }}</span>
        <div class="control-buttons-group">
          <button v-if="!isUTPaused" class="hp-button hp-button-warning hp-button-sm" @click="pauseUTGeneration" title="暂停生成">
            <Pause :size="16" class="hp-icon-sm" />
            <span class="btn-text">暂停</span>
          </button>
          <button v-if="isUTPaused" class="hp-button hp-button-success hp-button-sm" @click="resumeUTGeneration" title="继续生成">
            <Play :size="16" class="hp-icon-sm" />
            <span class="btn-text">继续</span>
          </button>
          <button class="hp-button hp-button-secondary hp-button-sm" @click="cancelUTGeneration" title="取消生成">
            <X :size="16" class="hp-icon-sm" />
            <span class="btn-text">取消</span>
          </button>
          <!-- 清屏按钮（放在控制按钮组内）-->
          <button class="hp-button hp-button-clear hp-button-sm" @click="clearScreen" title="清空聊天记录">
            <Trash2 :size="16" class="hp-icon-sm" />
            <span class="btn-text">清屏</span>
          </button>
        </div>
      </template>
      <!-- Fuzz 生成控制按钮 -->
      <template v-else-if="isGeneratingFuzz">
        <!-- 🔍 调试：在控制台输出渲染信息 -->
        <span style="display: none;">{{ console.log('[AiChat] 🎨 正在渲染 Fuzz 按钮, isGeneratingFuzz =', isGeneratingFuzz, ', isFuzzPaused =', isFuzzPaused) }}</span>
        <div class="control-buttons-group">
          <button v-if="!isFuzzPaused" class="control-btn pause-btn" @click="pauseFuzzGeneration" title="暂停生成">
            <svg class="btn-icon" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
              <rect x="6" y="4" width="4" height="16" rx="1" fill="currentColor"/>
              <rect x="14" y="4" width="4" height="16" rx="1" fill="currentColor"/>
            </svg>
            <span class="btn-text">暂停</span>
          </button>
          <button v-if="isFuzzPaused" class="control-btn resume-btn" @click="resumeFuzzGeneration" title="继续生成">
            <svg class="btn-icon" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
              <path d="M8 5v14l11-7L8 5z" fill="currentColor"/>
            </svg>
            <span class="btn-text">继续</span>
          </button>
          <button class="control-btn cancel-btn" @click="cancelFuzzGeneration" title="取消生成">
            <svg class="btn-icon" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
              <path d="M18 6L6 18M6 6l12 12" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
            </svg>
            <span class="btn-text">取消</span>
          </button>
          <!-- 清屏按钮（放在控制按钮组内）-->
          <button class="control-btn clear-btn" @click="clearScreen" title="清空聊天记录">
            <svg class="btn-icon" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
              <path d="M3 6h18M8 6V4a1 1 0 011-1h6a1 1 0 011 1v2m2 0v13a2 2 0 01-2 2H8a2 2 0 01-2-2V6h12z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
            </svg>
            <span class="btn-text">清屏</span>
          </button>
        </div>
      </template>
      <!-- 普通聊天停止按钮 -->
      <d-button v-else-if="isStreaming" icon="icon-stop" variant="solid" color="secondary" @click="stopResponse">
        停止回答
      </d-button>
      <!-- 🔍 调试：记录按钮显示状态 -->
      <span style="display: none;">{{ console.log('[AiChat] 🎨 按钮区域渲染完成，状态:', { isGeneratingUT, isGeneratingFuzz, isStreaming }) }}</span>
      
      <!-- 非生成状态时的独立清屏按钮 -->
      <button v-if="!isGeneratingUT && !isGeneratingFuzz && messages.length > 0" class="control-btn clear-btn" @click="clearScreen" title="清空聊天记录">
        <svg class="btn-icon" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
          <path d="M3 6h18M8 6V4a1 1 0 011-1h6a1 1 0 011 1v2m2 0v13a2 2 0 01-2 2H8a2 2 0 01-2-2V6h12z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
        </svg>
        <span class="btn-text">清屏</span>
      </button>
      
      <d-button icon="add" shape="circle" title="新建对话" size="sm" @click="onNewConvo" />
    </div>
    <div style="padding: 10px 12px 12px 12px">
      <McInput :value="inputValue" :maxLength="2000" :placeholder="placeholderText" @change="(e) => (inputValue = e)" @submit="onSubmit">
        <template #head v-if="showHighlightedCode">
          <div class="appendix-wrap">
            <div class="appendix-item">
              <span> {{ highlightedCode.fsPath }}</span>
              <span style="margin-left:5px;"> {{ highlightedCode.range }}</span>
              <i class="icon-code-editor-close" @click="highlightedCodeClick()"></i>
            </div>
          </div>
        </template>
        <template #extra>
          <div class="input-foot-wrapper">
            <div class="input-foot-left">
              <span class="input-foot-maxlength">{{ inputValue.length }}/2000</span>
            </div>
            <div class="input-foot-right">
              <d-button icon="op-clearup" shape="round" :disabled="!inputValue" @click="inputValue = ''">清空输入</d-button>
            </div>
          </div>
        </template>
      </McInput>
    </div>
  </div>
</template>

<script setup lang="ts">
import { nextTick, onMounted, ref, watch } from 'vue';
import { ThemeServiceInit, devuiLightTheme, devuiDarkTheme } from 'devui-theme';
import 'vue-devui/button/style.css';
import 'vue-devui/input/style.css';
import { marked } from 'marked';

// 🎨 现代化 UI 样式系统
import '../styles/modern-ui.css';

// 🎨 Lucide Icons - 现代化高质量SVG图标
import { 
  FolderOpen, CheckCircle2, XCircle, Play, Pause, X, 
  Loader2, CheckCheck, AlertCircle, Trash2
} from 'lucide-vue-next';

// LLM
import type { Tool } from '@anthropic-ai/sdk/resources/messages/messages.mjs';
// 初始是 infinityTheme 无限主题
const themeService = ThemeServiceInit(
  {
    'ide-light': devuiLightTheme,
    'ide-dark': devuiDarkTheme,
  },
  'ide-dark'
);
const theme = ref('dark');
const isStreaming = ref(false);
const isGeneratingUT = ref(false);  // 是否正在生成单元测试
const isUTPaused = ref(false);  // UT生成是否已暂停
const isGeneratingFuzz = ref(false);  // 是否正在生成Fuzz测试
const isFuzzPaused = ref(false);  // Fuzz生成是否已暂停
const isInUTContext = ref(false);  // 是否在单元测试上下文中（用于后续对话优化）

// 🔍 诊断日志：监控所有关键状态变化
console.log('[AiChat] 🚀 组件初始化，设置 watch 监听器');
watch(isGeneratingFuzz, (newVal, oldVal) => {
  console.log('[AiChat] 🔄 isGeneratingFuzz 变化:', { 旧值: oldVal, 新值: newVal });
  console.log('[AiChat] 📊 当前完整状态:', {
    isGeneratingFuzz: isGeneratingFuzz.value,
    isFuzzPaused: isFuzzPaused.value,
    isGeneratingUT: isGeneratingUT.value,
    isUTPaused: isUTPaused.value,
    isStreaming: isStreaming.value
  });
}, { immediate: true });

watch(isGeneratingUT, (newVal, oldVal) => {
  console.log('[AiChat] 🔄 isGeneratingUT 变化:', { 旧值: oldVal, 新值: newVal });
}, { immediate: true });

watch(isStreaming, (newVal, oldVal) => {
  console.log('[AiChat] 🔄 isStreaming 变化:', { 旧值: oldVal, 新值: newVal });
}, { immediate: true });
const controller = ref(new AbortController()); // 存储中断控制器
const selectedCodeInfo = ref(null);  // 保存选中的代码信息
const placeholderText = ref('请输入消息，并按 Enter 发送');  // 动态 placeholder
const logoPng = ref(`${window.staticPath}/resource/logo/Hi.svg`);
const logo2Png = ref(`${window.staticPath}/resource/logo/Hi.svg`);
const isAgentOpen = ref(false);
const conversationRef = ref();
const startChat = ref(false);
const autoScrollEnabled = ref(true);
const scrollThreshold = ref(50);
const toolCallsData = ref([]);
const agentList = ref([
  { label: 'MateChat', value: 'matechat', active: true },
  { label: 'InsCode', value: 'inscode' },
]);
const selectedAgent = ref(agentList.value[0]);

// MCP tools
let tools: Tool[] = [];

const onNewConvo = () => {
  // 如果正在流式响应，先停止响应
  if (isStreaming.value) {
    if (controller.value) {
      controller.value.abort(); // 中断请求
      controller.value = new AbortController();
    }
    
    // 向插件发送停止聊天请求的消息
    window?.vscode.postMessage({ 
      messageType: 'stopChatRequest', 
      data: {} 
    });
    
    isStreaming.value = false;
  }
};

/**
 * 清屏功能（新增）
 * 清空聊天记录，重置相关状态
 */
const clearScreen = () => {
  // 1. 停止任何正在进行的流式响应
  if (isStreaming.value) {
    if (controller.value) {
      controller.value.abort();
      controller.value = new AbortController();
    }
    window?.vscode.postMessage({ 
      messageType: 'stopChatRequest', 
      data: {} 
    });
    isStreaming.value = false;
  }
  
  // 2. 取消正在进行的 UT 生成
  if (isGeneratingUT.value) {
    window?.vscode.postMessage({ 
      messageType: 'cancelUTGeneration', 
      data: {} 
    });
    isGeneratingUT.value = false;
    isUTPaused.value = false;
  }
  
  // 3. 取消正在进行的 Fuzz 生成
  if (isGeneratingFuzz.value) {
    window?.vscode.postMessage({ 
      messageType: 'cancelFuzzGeneration', 
      data: {} 
    });
    isGeneratingFuzz.value = false;
    isFuzzPaused.value = false;
  }
  
  // 4. 清空消息列表
  messages.value = [];
  deepseekMessages.value = [];
  
  // 5. 重置其他状态
  isInUTContext.value = false;
  startChat.value = false;
  inputValue.value = '';
  
  console.log('[AiChat] 🗑️ 清屏完成');
};
const stopResponse = () => {
  // 如果有消息存在，设置最后一条消息的状态
  if (messages.value.length > 0) {
    messages.value[messages.value.length - 1].isStop = true;
    messages.value[messages.value.length - 1].loading = false;
  }
  
  if (controller.value) {
    controller.value.abort(); // 触发请求中断‌:ml-citation{ref="7" data="citationList"}
    controller.value = new AbortController();
    isStreaming.value = false;
  }
  
  // 向插件发送停止聊天请求的消息
  window?.vscode.postMessage({ 
    messageType: 'stopChatRequest', 
    data: {} 
  });
  
  // 清空历史记录
  deepseekMessages.value = [];
};
const inputValue = ref('');
const highlightedCode = ref({
  fsPath: '',
  contents: '',
  range: '',
  orginContents: ''
});
const showHighlightedCode = ref(false);
// @ts-ignore
const inputFootIcons = [
  { icon: 'icon-at', text: '智能体' },
  { icon: 'icon-standard', text: '词库' },
  { icon: 'icon-add', text: '附件' },
];
const messages = ref([]);
const deepseekMessages = ref([]);
// @ts-ignore
const onInputIconClick = (e) => {
  if (e.icon === 'icon-at') {
    inputValue.value += `@${selectedAgent.value.label}`;
  }
};
const onSubmit = (evt) => {
  // 如果正在生成单元测试，且在UT上下文中，处理优化反馈
  if (isGeneratingUT.value && !isStreaming.value && isInUTContext.value) {
    inputValue.value = '';
    
    // 发送回答到后端
    window?.vscode.postMessage({ 
      messageType: 'utChatMessage',  // 🔧 修复：统一使用 utChatMessage
      data: {
        message: evt  // 🔧 修复：统一使用 message 字段
      }
    });
    
    // 添加用户消息
    messages.value.push({
      from: 'user',
      content: evt,
      avatarPosition: 'side-right',
    });
    
    // 添加 AI 思考消息
    messages.value.push({
      from: 'ai-model',
      content: '💭 正在处理您的回答...',
      avatarPosition: 'side-left',
      loading: true,
      isStop: false,
    });
    
    nextTick(() => {
      if (autoScrollEnabled.value) {
        scrollToBottom();
      }
    });
    return;
  }
  
  if (isStreaming.value) {
    window?.vscode.postMessage({ messageType: 'wait', data: '请等待上一次回答完成后再进行操作'});
    return;
  }
  isStreaming.value = true;
  inputValue.value = '';
  if (!messages.value.length) {
    startChat.value = true;
  }
  
  let sendStr = '';
  let displayStr = '';
  
  // 如果有选中的代码信息，在用户消息前添加代码上下文
  if (selectedCodeInfo.value) {
    const codeInfo = selectedCodeInfo.value;
    const language = ['cpp', 'cc', 'cxx', 'c++', 'h', 'hpp'].includes(codeInfo.fileName.split('.').pop()?.toLowerCase() || '') ? 'cpp' : 'text';
    
    const codeContext = `我选中了 **${codeInfo.fileName}** 的 **第 ${codeInfo.startLine}-${codeInfo.endLine} 行**代码：

\`\`\`${language}
${codeInfo.selectedText}
\`\`\`

`;
    
    sendStr = codeContext + evt;
    displayStr = codeContext + evt;
    
    // 清空选中代码信息和恢复 placeholder
    selectedCodeInfo.value = null;
    placeholderText.value = '请输入消息，并按 Enter 发送';
  } else if (showHighlightedCode.value) {
    sendStr = highlightedCode.value.orginContents + evt;
    const fsPath = highlightedCode.value.fsPath.replace('.','.​');
    displayStr = `**${fsPath}${highlightedCode.value.range}**\n
    
    \n${evt}`;
  } else {
    sendStr = evt;
    displayStr = evt;
  }
  
  // 用户发送消息
  messages.value.push({
    from: 'user',
    content: displayStr,
    avatarPosition: 'side-right',
  });
  deepseekMessages.value.push({
    role: 'user',
    content: sendStr
  });
  nextTick(() => {
    if (autoScrollEnabled.value) {
      scrollToBottom();
    }
  });
  fetchData();
};
const scrollToBottom = () => {
  conversationRef.value?.scrollTo({
    top: conversationRef.value.scrollHeight,
    behavior: 'smooth',
  });
}
watch(() => startChat.value, (newValue) => {
  if (newValue) {
    setTimeout(() => {
      if (conversationRef.value) {
        conversationRef.value.addEventListener('scroll', () => {
          const isNearBottom = conversationRef.value.scrollTop + conversationRef.value.clientHeight >= conversationRef.value.scrollHeight - scrollThreshold.value;
          autoScrollEnabled.value = isNearBottom;
        });
      }
    });
  }
});
onMounted(() => {
  // 页面加载时请求MCP工具列表
  window?.vscode.postMessage({ 
    messageType: 'requestMcpTools', 
    data: {} 
  });

  // Webview前端代码
  window.addEventListener('message', event => {
    const message = event.data;
    switch (message.messageType) {
      case 'highlightedCode':
        showHighlightedCode.value = true;
        const codeData = message.data.rangeInFileWithContents;
        renderHighlightedCode(codeData);
        break;
      case 'mcpToolsUpdated':
        handleMcpTools(message.data.tools);
        break;
      case 'toolCallsResult':
        handleToolCallsResult(message.data);
        break;
      case 'streamChunk':
        handleStreamChunk(message.data);
        break;
      case 'streamEnd':
        handleStreamEnd();
        break;
      case 'streamToolCalls':
        handleStreamToolCalls(message.data);
        break;
      case 'streamError':
        handleStreamError(message.data);
        break;
      case 'themeChange':
        themeChange(message.data.isDark);
        break;
      case 'utQuestion':
        handleUTQuestion(message.data);
        break;
      case 'utInfo':
        handleUTInfo(message.data);
        break;
      case 'utCodeChunk':
        handleUTCodeChunk(message.data);
        break;
      case 'utTextChunk':
        handleUTTextChunk(message.data);
        break;
      case 'utComplete':
        handleUTComplete(message.data);
        break;
      case 'utError':
        handleUTError(message.data);
        break;
      case 'utFileAction':
        handleUTFileAction(message.data);
        break;
      case 'utFileInfo':
        handleUTFileInfo(message.data);
        break;
      case 'selectedCodeForUT':
        console.log('[AiChat] 接收到 selectedCodeForUT 消息:', message.data);
        handleSelectedCodeForUT(message.data);
        break;
      case 'selectedCodeForFuzz':
        console.log('[AiChat] 接收到 selectedCodeForFuzz 消息:', message.data);
        handleSelectedCodeForFuzz(message.data);
        break;
      case 'fuzzInfo':
        handleFuzzInfo(message.data);
        break;
      case 'fuzzWarning':
        handleFuzzWarning(message.data);
        break;
      case 'fuzzError':
        handleFuzzError(message.data);
        break;
      case 'fuzzProgress':
        handleFuzzProgress(message.data);
        break;
      case 'fuzzTextChunk':
        handleFuzzTextChunk(message.data);
        break;
      case 'fuzzFileCreated':
        handleFuzzFileCreated(message.data);
        break;
      case 'fuzzComplete':
        handleFuzzComplete(message.data);
        break;
    }
  });
  window.addEventListener('load', () => {
    window?.vscode.postMessage({ messageType: 'webviewLoaded', data: '' });
  });
  window.vscode.postMessage({ messageType: 'getTheme' });
});

function handleStreamChunk(data) {
  if (data.content) {
    messages.value[messages.value.length - 1].content += data.content;
    nextTick(() => {
      if (autoScrollEnabled.value) {
        scrollToBottom();
      }
    });
  }
}

function handleStreamEnd() {
  const lastMessage = messages.value[messages.value.length - 1];
  lastMessage.loading = false;
  isStreaming.value = false;

  console.log("==============Streamend, toolcallsData's length is ", toolCallsData.value.length)

  if (toolCallsData.value.length > 0) {
    // 序列化工具调用数据以确保可以传输
    const serializedToolCalls = JSON.parse(JSON.stringify(toolCallsData.value));
    
    deepseekMessages.value.push({
      role: 'assistant',
      content: null,
      tool_calls: serializedToolCalls
    });
    window?.vscode.postMessage({
      messageType: 'toolCallsDetected',
      data: {
        toolCalls: serializedToolCalls
      }
    });
    toolCallsData.value = [];
  } else {
    deepseekMessages.value.push({
      role: 'assistant',
      content: lastMessage.content
    });
  }
}

function handleStreamToolCalls(data) {
  const lastMessage = messages.value[messages.value.length - 1];
  lastMessage.content = '执行MCP工具中..';
  moveToBottom();
  toolCallsData.value = data.toolCalls;
}

function handleStreamError(data) {
  const lastMessage = messages.value[messages.value.length - 1];
  lastMessage.content = `发生错误: ${data.error}`;
  lastMessage.loading = false;
  isStreaming.value = false;
  console.error('Stream error:', data.error);
}

function handleToolCallsResult(toolCalls) {
  for (const toolCall of toolCalls.data) {
    deepseekMessages.value.push({
      role: 'tool',
      tool_call_id: toolCall.tool_call_id,
      content: toolCall.content
    });
  }
  fetchData();
}

function renderHighlightedCode({ filepath, range, contents }) {
  const filePathInfo = decodeURIComponent(filepath.split('/')[filepath.split('/').length - 1]);
  highlightedCode.value = {
    fsPath: filePathInfo,
    contents: getCodeHtml(contents),
    orginContents: contents,
    range: `(${range.start.line + 1}-${range.end.line + 1})`
  };
}
const getCodeHtml = (contents) => {
  const codeWrapper = '```';
  const language = 'vue';
  const markedStr = marked.parse(`${codeWrapper}${language}\r\n${contents}\r\n${codeWrapper}`);
  return appendCodeToTarget(markedStr, {
    needCodeOperateBar: false,
    minCodeLine: 3,
    isExpand: false
  });
};
// @ts-ignore
const appendCodeToTarget = (markedStr, data = {}) => {
  const container = document.createElement('div');
  container.innerHTML = markedStr;
  return container.innerHTML;
}

const fetchData = async () => {
  try {
    highlightedCodeClick();
    
    // 检查是否在单元测试上下文中
    if (isInUTContext.value) {
      // 在单元测试上下文中，发送优化请求
      const userMessage = messages.value[messages.value.length - 1].content;
      
      messages.value.push({
        from: 'ai-model',
        content: '💭 正在根据您的反馈优化...',
        avatarPosition: 'side-left',
        loading: true,
        isStop: false,
      });
      
      window?.vscode.postMessage({
        messageType: 'utChatMessage',
        data: {
          message: userMessage
        }
      });
      
      return;
    }
    
    // 普通聊天流程
    messages.value.push({
      from: 'ai-model',
      content: '',
      avatarPosition: 'side-left',
      loading: true,
      isStop: false,
    });

    const available_tools = tools.map((tool) => {
      return {
        type: "function",
        function: {
          name: tool.name,
          description: tool.description,
          parameters: tool.input_schema
        }
      };
    });

    const requestOptions: { model: string, messages: any, stream: boolean, tools?: any } = {
      model: "deepseek-chat",
      messages: deepseekMessages.value as any,
      stream: true
    };
    
    if (available_tools.length > 0) {
      requestOptions.tools = available_tools;
    }

    window?.vscode.postMessage({
      messageType: 'chatRequest',
      data: JSON.stringify(requestOptions)
    });

  } catch (err) {
    if (err.name === 'CanceledError') {
      console.log('用户主动终止');
    }
  } 
};

const moveToBottom = () => {
  nextTick(() => {
    if (autoScrollEnabled.value) {
      scrollToBottom();
    }
  });
}

const highlightedCodeClick = () => {
  showHighlightedCode.value = false;
  highlightedCode.value = {
    fsPath: '',
    contents: '',
    orginContents: '',
    range: ''
  };
};
const insertCodeAtCursor = (codeBlockData) => {
  window?.vscode.postMessage({ messageType: 'insertCode', data: codeBlockData });
};

const copyText = (codeBlockData) => {
  window?.vscode.postMessage({ messageType: 'copyText', data: codeBlockData });
};


// const connectToServer = async () => {
//   for (const [serverName, serverConfig] of availableMCPServers.entries()) {
    
//     const transport = new StdioClientTransport({
//         command: serverConfig.command,
//         args: serverConfig.args,
//     });
//     await mcp.connect(transport);
    
//     // Register tools
//     const toolsResult = await mcp.listTools();
//     toolsResult.tools.map((tool) => {
//       tools.push({
//         name: tool.name,
//         description: tool.description,
//         input_schema: {
//           ...tool.inputSchema,
//           type: tool.inputSchema.type || "object"
//         },
//       });
//     });
//   }
// }

// 处理从插件接收到的工具列表
const handleMcpTools = (toolsList) => {
  tools = toolsList;
  console.log(`Received ${tools.length} MCP tools from extension`);
  showMcpConfigUpdateNotification(true);
};


// 显示MCP配置更新通知
const showMcpConfigUpdateNotification = (success: boolean, error?: any) => {
  // 向VS Code发送消息，显示通知
  if (success) {
    window?.vscode.postMessage({ 
      messageType: 'notification', 
      data: 'MCP配置已成功更新并应用'
    });
    
  } else {
    window?.vscode.postMessage({ 
      messageType: 'notification', 
      data: `MCP配置更新失败: ${error?.message || '未知错误'}` 
    });
  }
};
const themeChange = (isDark: true) => {
  if (themeService) {
    theme.value = isDark  ? 'dark' : 'light';
    themeService.applyTheme(isDark ? devuiDarkTheme : devuiLightTheme);
  }
};

// 处理单元测试问题
const handleUTQuestion = (data) => {
  // 添加新的问题消息，而不是覆盖之前的消息
  messages.value.push({
    from: 'ai-model',
    content: `💬 **${data.question}**\n\n请在下方输入框回答此问题。`,
    avatarPosition: 'side-left',
    loading: false,
    isStop: false,
  });
  
  isGeneratingUT.value = false;
  
  nextTick(() => {
    if (autoScrollEnabled.value) {
      scrollToBottom();
    }
  });
};

// 处理单元测试信息消息（步骤进度）
const handleUTInfo = (data) => {
  // 添加步骤进度消息
  messages.value.push({
    from: 'ai-model',
    content: data.message,
    avatarPosition: 'side-left',
    loading: false,
    isStop: false,
  });
  
  nextTick(() => {
    if (autoScrollEnabled.value) {
      scrollToBottom();
    }
  });
};

// 处理文件信息（只读，只有查看按钮）
const handleUTFileInfo = (data) => {
  console.log('[AiChat] 📥 收到 utFileInfo 消息:', data);
  
  const { fileType, filePath, displayPath, label } = data;
  
  console.log('[AiChat]    文件类型:', fileType);
  console.log('[AiChat]    标签:', label);
  console.log('[AiChat]    显示路径:', displayPath);
  console.log('[AiChat]    实际路径:', filePath);
  
  // 创建带查看按钮的消息
  const content = `📄 ${label}`;
  
  messages.value.push({
    from: 'ai-model',
    content: content,
    avatarPosition: 'side-left',
    loading: false,
    isStop: false,
    fileInfo: {
      fileType,
      filePath,
      displayPath,
      label
    }
  });
  
  console.log('[AiChat] ✅ 已添加文件信息到消息列表，消息总数:', messages.value.length);
  
  nextTick(() => {
    if (autoScrollEnabled.value) {
      scrollToBottom();
    }
  });
};

// 处理文件操作请求（采纳/拒绝）
const handleUTFileAction = (data) => {
  const { actionId, fileType, filePath, displayPath, action } = data;
  const actionText = action === 'create' ? '创建' : '修改';
  const fileTypeText = fileType === 'test' ? '测试文件' : 'GN 配置';
  
  // 创建带按钮的消息 - 路径在按钮区域显示，这里只显示操作类型
  const content = `📝 ${actionText}${fileTypeText}`;
  
  messages.value.push({
    from: 'ai-model',
    content: content,
    avatarPosition: 'side-left',
    loading: false,
    isStop: false,
    fileAction: {
      actionId,
      fileType,
      filePath,
      displayPath,
      action
    }
  });
  
  nextTick(() => {
    if (autoScrollEnabled.value) {
      scrollToBottom();
    }
  });
};

// 打开文件
const openFile = (filePath: string) => {
  console.log('[AiChat] 📂 请求打开文件:', filePath);
  
  // 发送打开文件请求到后端
  window.vscode.postMessage({
    messageType: 'openFile',
    data: {
      filePath
    }
  });
  
  console.log('[AiChat] ✅ openFile 消息已发送到后端');
};

// 处理用户点击采纳/拒绝按钮
const handleFileActionResponse = (actionId: string, decision: 'accept' | 'reject') => {
  // 发送决策到后端
  window.vscode.postMessage({
    messageType: 'fileActionResponse',
    data: {
      actionId,
      decision
    }
  });
  
  // 找到对应的消息并更新状态
  const messageIndex = messages.value.findIndex(msg => msg.fileAction?.actionId === actionId);
  if (messageIndex !== -1) {
    const msg = messages.value[messageIndex];
    msg.fileAction.decided = decision;
    
    // 添加反馈消息
    const feedbackText = decision === 'accept' ? '✅ 已采纳' : '❌ 已拒绝';
    messages.value.push({
      from: 'ai-model',
      content: `${feedbackText} ${msg.fileAction.displayPath}`,
      avatarPosition: 'side-left',
      loading: false,
      isStop: false,
    });
  }
};

// 处理单元测试代码块
const handleUTCodeChunk = (data) => {
  const lastMessage = messages.value[messages.value.length - 1];
  
  // 如果最后一条消息是代码消息，追加内容
  if (lastMessage && lastMessage.content && lastMessage.content.startsWith('```')) {
    // 移除结尾的 ```（如果有）
    if (lastMessage.content.endsWith('```')) {
      lastMessage.content = lastMessage.content.slice(0, -3);
    }
    lastMessage.content += data.content;
  } else {
    // 创建新的代码块消息
    messages.value.push({
      from: 'ai-model',
      content: '```cpp\n' + data.content,
      avatarPosition: 'side-left',
      loading: false,
      isStop: false,
    });
  }
  
  nextTick(() => {
    if (autoScrollEnabled.value) {
      scrollToBottom();
    }
  });
};

// 处理单元测试普通文本块（用于对话回复）
const handleUTTextChunk = (data) => {
  const lastMessage = messages.value[messages.value.length - 1];
  
  // 如果最后一条消息是AI消息且不是加载中，追加内容
  if (lastMessage && lastMessage.from === 'ai-model' && !lastMessage.loading) {
    lastMessage.content += data.content;
  } else {
    // 创建新的文本消息
    messages.value.push({
      from: 'ai-model',
      content: data.content,
      avatarPosition: 'side-left',
      loading: false,
      isStop: false,
    });
  }
  
  nextTick(() => {
    if (autoScrollEnabled.value) {
      scrollToBottom();
    }
  });
};

// 暂停UT生成
const pauseUTGeneration = () => {
  console.log('[AiChat] ⏸️ 暂停UT生成');
  isUTPaused.value = true;
  window?.vscode.postMessage({
    messageType: 'pauseUTGeneration',
    data: {}
  });
};

// 继续UT生成
const resumeUTGeneration = () => {
  console.log('[AiChat] ▶️ 继续UT生成');
  isUTPaused.value = false;
  window?.vscode.postMessage({
    messageType: 'resumeUTGeneration',
    data: {}
  });
};

// 取消UT生成
const cancelUTGeneration = () => {
  console.log('[AiChat] ❌ 取消UT生成');
  isGeneratingUT.value = false;
  isUTPaused.value = false;
  window?.vscode.postMessage({
    messageType: 'cancelUTGeneration',
    data: {}
  });
  
  // 添加取消提示消息
  messages.value.push({
    from: 'ai-model',
    content: '⚠️ 操作已取消',
    avatarPosition: 'side-left',
    loading: false,
    isStop: false,
  });
  
  nextTick(() => {
    if (autoScrollEnabled.value) {
      scrollToBottom();
    }
  });
};

// 暂停Fuzz生成
const pauseFuzzGeneration = () => {
  console.log('[AiChat] ⏸️ 用户点击暂停Fuzz生成');
  isFuzzPaused.value = true;
  console.log('[AiChat] 暂停标志已设置:', { isFuzzPaused: isFuzzPaused.value });
  window?.vscode.postMessage({
    messageType: 'pauseFuzzGeneration',
    data: {}
  });
};

// 继续Fuzz生成
const resumeFuzzGeneration = () => {
  console.log('[AiChat] ▶️ 用户点击继续Fuzz生成');
  isFuzzPaused.value = false;
  console.log('[AiChat] 继续标志已设置:', { isFuzzPaused: isFuzzPaused.value });
  window?.vscode.postMessage({
    messageType: 'resumeFuzzGeneration',
    data: {}
  });
};

// 取消Fuzz生成
const cancelFuzzGeneration = () => {
  console.log('[AiChat] ❌ 用户点击取消Fuzz生成');
  isGeneratingFuzz.value = false;
  isFuzzPaused.value = false;
  console.log('[AiChat] 取消标志已清除:', {
    isGeneratingFuzz: isGeneratingFuzz.value,
    isFuzzPaused: isFuzzPaused.value
  });
  
  window?.vscode.postMessage({
    messageType: 'cancelFuzzGeneration',
    data: {}
  });
  
  // 添加取消提示消息
  messages.value.push({
    from: 'ai-model',
    content: '⚠️ Fuzz测试生成已取消',
    avatarPosition: 'side-left',
    loading: false,
    isStop: false,
  });
  
  nextTick(() => {
    if (autoScrollEnabled.value) {
      scrollToBottom();
    }
  });
};

// 处理单元测试完成
const handleUTComplete = (data) => {
  isGeneratingUT.value = false;
  isUTPaused.value = false;
  
  // 确保最后一条代码消息正确关闭
  const lastMessage = messages.value[messages.value.length - 1];
  if (lastMessage && lastMessage.content && lastMessage.content.startsWith('```') && !lastMessage.content.endsWith('```')) {
    lastMessage.content += '\n```';
  }
  
  // 移除"正在优化"的临时消息
  const lastTempMessage = messages.value[messages.value.length - 1];
  if (lastTempMessage && lastTempMessage.content && lastTempMessage.content.includes('💭 正在根据您的反馈优化')) {
    messages.value.pop();
  }
  
  // 添加完成消息
  messages.value.push({
    from: 'ai-model',
    content: `✅ ${data.message}\n\n你可以继续在聊天中提出修改意见，例如：\n- "添加边界条件测试"\n- "增加 Mock 对象"\n- "优化测试用例命名"`,
    avatarPosition: 'side-left',
    loading: false,
  });
  
  // 保持在单元测试上下文中，允许继续对话
  // isInUTContext.value 保持为 true，不需要修改
  
  nextTick(() => {
    if (autoScrollEnabled.value) {
      scrollToBottom();
    }
  });
};

// 处理单元测试错误
const handleUTError = (data) => {
  isGeneratingUT.value = false;
  isUTPaused.value = false;
  const lastMessage = messages.value[messages.value.length - 1];
  lastMessage.content = `❌ 生成失败: ${data.error}`;
  lastMessage.loading = false;
};

// 处理右键菜单选中代码生成单元测试
const handleSelectedCodeForUT = (data) => {
  console.log('[AiChat] handleSelectedCodeForUT 被调用, data:', data);
  
  // 检查是否有其他任务正在执行
  if (isGeneratingFuzz.value) {
    console.log('[AiChat] ⚠️ Fuzz 测试正在生成，拒绝 UT 请求');
    messages.value.push({
      from: 'ai-model',
      content: '⚠️ **当前正在生成 Fuzz 测试**\n\n请等待 Fuzz 测试生成完成后，再生成单元测试。\n\n您可以点击 **取消** 按钮停止当前任务。',
      avatarPosition: 'side-left',
      loading: false,
      isStop: false,
    });
    nextTick(() => {
      if (autoScrollEnabled.value) {
        scrollToBottom();
      }
    });
    return;
  }
  
  if (isStreaming.value || isGeneratingUT.value) {
    window?.vscode.postMessage({ 
      messageType: 'wait', 
      data: '请等待当前操作完成'
    });
    return;
  }
  
  // 立即设置UT生成标志，显示控制按钮
  isGeneratingUT.value = true;
  isUTPaused.value = false;
  isInUTContext.value = true;
  console.log('[AiChat] ✅ 已设置 UT 生成标志:', {
    isGeneratingUT: isGeneratingUT.value,
    isUTPaused: isUTPaused.value,
    isGeneratingFuzz: isGeneratingFuzz.value,
    isStreaming: isStreaming.value
  });
  
  // 保存选中的代码信息
  selectedCodeInfo.value = {
    fileName: data.fileName,
    startLine: data.startLine,
    endLine: data.endLine,
    selectedText: data.selectedText,
    filePath: data.filePath,
    isWholeFile: data.isWholeFile || false
  };
  
  console.log('[AiChat] selectedCodeInfo 已保存:', selectedCodeInfo.value);
  
  // 聚焦到 AiChat（如果还没打开）
  if (!messages.value.length) {
    startChat.value = true;
    console.log('[AiChat] 开始聊天');
  }
  
  // 直接使用Agent模式生成单元测试
  startUTGenerationWithMode();
};

// 处理右键菜单选中代码生成Fuzz测试
const handleSelectedCodeForFuzz = (data) => {
  console.log('[AiChat] handleSelectedCodeForFuzz 被调用, data:', data);
  
  // 检查是否有其他任务正在执行
  if (isGeneratingUT.value) {
    console.log('[AiChat] ⚠️ 单元测试正在生成，拒绝 Fuzz 请求');
    messages.value.push({
      from: 'ai-model',
      content: '⚠️ **当前正在生成单元测试**\n\n请等待单元测试生成完成后，再生成 Fuzz 测试。\n\n您可以点击 **取消** 按钮停止当前任务。',
      avatarPosition: 'side-left',
      loading: false,
      isStop: false,
    });
    nextTick(() => {
      if (autoScrollEnabled.value) {
        scrollToBottom();
      }
    });
    return;
  }
  
  if (isStreaming.value || isGeneratingFuzz.value) {
    window?.vscode.postMessage({ 
      messageType: 'wait', 
      data: '请等待当前操作完成'
    });
    return;
  }
  
  // 立即设置Fuzz生成标志，显示控制按钮
  console.log('[AiChat] 🎯 准备设置 Fuzz 生成标志...');
  console.log('[AiChat] 📊 设置前:', {
    isGeneratingFuzz: isGeneratingFuzz.value,
    isFuzzPaused: isFuzzPaused.value,
    isGeneratingUT: isGeneratingUT.value,
    isStreaming: isStreaming.value
  });
  
  isGeneratingFuzz.value = true;
  isFuzzPaused.value = false;
  
  console.log('[AiChat] ✅ 已设置 Fuzz 生成标志（立即检查）:', {
    isGeneratingFuzz: isGeneratingFuzz.value,
    isFuzzPaused: isFuzzPaused.value,
    isGeneratingUT: isGeneratingUT.value,
    isStreaming: isStreaming.value
  });
  
  // 延迟100ms再次检查，确保Vue响应式系统已更新
  setTimeout(() => {
    console.log('[AiChat] 🔍 延迟检查 (100ms后):', {
      isGeneratingFuzz: isGeneratingFuzz.value,
      isFuzzPaused: isFuzzPaused.value,
      isGeneratingUT: isGeneratingUT.value,
      isStreaming: isStreaming.value
    });
  }, 100);
  
  // 聚焦到 AiChat（如果还没打开）
  if (!messages.value.length) {
    startChat.value = true;
    console.log('[AiChat] 开始聊天');
  }
  
  // 构建提示消息
  let promptMessage = '';
  
  if (data.isWholeFile) {
    promptMessage = `请为文件 **${data.fileName}** 生成 Fuzz 测试用例。

📁 **文件信息**
- 文件名：\`${data.fileName}\`
- 文件路径：\`${data.filePath}\`
- 总行数：${data.endLine} 行

Fuzz 测试将包括：
1. 🎲 生成随机输入数据
2. 🔍 边界值和异常情况测试
3. 💥 崩溃和异常检测
4. 📊 覆盖率最大化策略`;
  } else {
    promptMessage = `请为 **${data.fileName}** 的第 **${data.startLine}-${data.endLine}** 行代码生成 Fuzz 测试用例。

📁 **选中代码信息**
- 文件名：\`${data.fileName}\`
- 文件路径：\`${data.filePath}\`
- 代码行数：${data.startLine}-${data.endLine} 行

Fuzz 测试将包括：
1. 🎲 生成随机输入数据
2. 🔍 边界值和异常情况测试
3. 💥 崩溃和异常检测
4. 📊 覆盖率最大化策略`;
  }
  
  // 添加用户消息
  messages.value.push({
    from: 'user',
    content: `为以下代码生成 Fuzz 测试用例：\n\n\`\`\`cpp\n${data.selectedText.substring(0, 500)}${data.selectedText.length > 500 ? '\n...(更多代码)' : ''}\n\`\`\``,
    avatarPosition: 'side-right',
    loading: false,
    isStop: false,
  });
  
  // 添加AI消息
  messages.value.push({
    from: 'ai-model',
    content: promptMessage,
    avatarPosition: 'side-left',
    loading: true,
    isStop: false,
  });
  
  nextTick(() => {
    if (autoScrollEnabled.value) {
      scrollToBottom();
    }
  });
  
  // 发送生成 Fuzz 测试的请求
  setTimeout(() => {
    const lastMsg = messages.value[messages.value.length - 1];
    lastMsg.loading = false;
    
    // 触发真正的 Fuzz 测试生成
    window?.vscode.postMessage({ 
      messageType: 'generateFuzzTest',
      data: {
        filePath: data.filePath,
        selectedText: data.selectedText,
        isWholeFile: data.isWholeFile
      }
    });
  }, 1000);
};

// 处理 Fuzz 测试信息消息（步骤进度）
const handleFuzzInfo = (data) => {
  // 添加步骤进度消息
  messages.value.push({
    from: 'ai-model',
    content: data.message,
    avatarPosition: 'side-left',
    loading: false,
    isStop: false,
  });
  
  nextTick(() => {
    if (autoScrollEnabled.value) {
      scrollToBottom();
    }
  });
  
  // 如果有文件路径，可以点击跳转
  if (data.filePath) {
    console.log('[AiChat] Fuzz 文件路径:', data.filePath);
  }
};

// 处理 Fuzz 测试警告消息
const handleFuzzWarning = (data) => {
  messages.value.push({
    from: 'ai-model',
    content: `⚠️ ${data.message}`,
    avatarPosition: 'side-left',
    loading: false,
    isStop: false,
  });
  
  nextTick(() => {
    if (autoScrollEnabled.value) {
      scrollToBottom();
    }
  });
};

// 处理 Fuzz 测试错误消息
const handleFuzzError = (data) => {
  console.log('[AiChat] ⚠️ Fuzz 生成出错，重置标志');
  console.log('[AiChat] 📊 重置前状态:', {
    isGeneratingFuzz: isGeneratingFuzz.value,
    isFuzzPaused: isFuzzPaused.value
  });
  
  isGeneratingFuzz.value = false;
  isFuzzPaused.value = false;
  
  console.log('[AiChat] 📊 重置后状态:', {
    isGeneratingFuzz: isGeneratingFuzz.value,
    isFuzzPaused: isFuzzPaused.value
  });
  
  messages.value.push({
    from: 'ai-model',
    content: `❌ **生成失败**\n\n${data.error}`,
    avatarPosition: 'side-left',
    loading: false,
    isStop: false,
  });
  
  nextTick(() => {
    if (autoScrollEnabled.value) {
      scrollToBottom();
    }
  });
};

// 处理 Fuzz 测试进度消息
const handleFuzzProgress = (data) => {
  // 更新最后一条消息或添加新消息
  const lastMsg = messages.value[messages.value.length - 1];
  if (lastMsg && lastMsg.loading) {
    lastMsg.content = data.message;
    lastMsg.loading = false;
  } else {
    messages.value.push({
      from: 'ai-model',
      content: data.message,
      avatarPosition: 'side-left',
      loading: true,
      isStop: false,
    });
  }
  
  nextTick(() => {
    if (autoScrollEnabled.value) {
      scrollToBottom();
    }
  });
};

// 处理 Fuzz 测试文本流式输出
const handleFuzzTextChunk = (data) => {
  const lastMsg = messages.value[messages.value.length - 1];
  
  // 如果最后一条消息是AI消息且不是加载中，追加内容
  if (lastMsg && lastMsg.from === 'ai-model' && !lastMsg.loading) {
    lastMsg.content += data.content;
  } else {
    // 创建新的文本消息
    messages.value.push({
      from: 'ai-model',
      content: data.content,
      avatarPosition: 'side-left',
      loading: false,
      isStop: false,
    });
  }
  
  nextTick(() => {
    if (autoScrollEnabled.value) {
      scrollToBottom();
    }
  });
};

// 处理 Fuzz 测试文件创建消息
const handleFuzzFileCreated = (data) => {
  messages.value.push({
    from: 'ai-model',
    content: data.message,
    avatarPosition: 'side-left',
    loading: false,
    isStop: false,
  });
  
  nextTick(() => {
    if (autoScrollEnabled.value) {
      scrollToBottom();
    }
  });
};

// 处理 Fuzz 测试完成消息
const handleFuzzComplete = (data) => {
  console.log('[AiChat] ✅ Fuzz 生成完成，重置标志');
  console.log('[AiChat] 📊 重置前状态:', {
    isGeneratingFuzz: isGeneratingFuzz.value,
    isFuzzPaused: isFuzzPaused.value
  });
  
  isGeneratingFuzz.value = false;
  isFuzzPaused.value = false;
  
  console.log('[AiChat] 📊 重置后状态:', {
    isGeneratingFuzz: isGeneratingFuzz.value,
    isFuzzPaused: isFuzzPaused.value
  });
  
  messages.value.push({
    from: 'ai-model',
    content: data.message,
    avatarPosition: 'side-left',
    loading: false,
    isStop: false,
  });
  
  nextTick(() => {
    if (autoScrollEnabled.value) {
      scrollToBottom();
    }
  });
};

// 启动UT生成（仅使用Agent模式）
const startUTGenerationWithMode = () => {
  const data = selectedCodeInfo.value;
  if (!data) {
    window?.vscode.postMessage({ 
      messageType: 'wait', 
      data: '未找到代码信息，请重新选择'
    });
    isGeneratingUT.value = false;
    return;
  }
  
  let codeContent = '';
  
  if (data.isWholeFile) {
    // 没有选中代码，使用整个文件
    codeContent = `好的，使用 **智能体模式** 为 **${data.fileName}** 生成单元测试。

📁 **文件信息**
- 文件名：\`${data.fileName}\`
- 文件路径：\`${data.filePath}\`
- 总行数：${data.endLine} 行

接下来我将自动执行以下步骤：
1. 📖 分析 ${data.fileName} 的代码结构
2. 🔍 查找 ${data.fileName} 所属的 GN 配置文件
3. 🧪 检查是否已存在单元测试文件
4. 📝 生成或更新单元测试代码
5. ⚙️ 修改相应的 GN 配置文件
6. ✅ 提供采纳/拒绝选项

让我开始吧...`;
  } else {
    // 选中了部分代码
    codeContent = `好的，使用 **智能体模式** 为 **${data.fileName}** 的第 **${data.startLine}-${data.endLine}** 行代码生成单元测试。

📁 **选中代码信息**
- 文件名：\`${data.fileName}\`
- 文件路径：\`${data.filePath}\`
- 代码行数：${data.startLine}-${data.endLine} 行

接下来我将自动执行以下步骤：
1. 📖 分析选中代码的功能和结构
2. 🔍 查找 ${data.fileName} 所属的 GN 配置文件
3. 🧪 检查是否已存在单元测试文件
4. 📝 为选中代码生成单元测试
5. ⚙️ 修改相应的 GN 配置文件
6. ✅ 提供采纳/拒绝选项

让我开始吧...`;
  }
  
  // 添加 AI 消息
  messages.value.push({
    from: 'ai-model',
    content: codeContent,
    avatarPosition: 'side-left',
    loading: false,
    isStop: false,
  });
  
  nextTick(() => {
    if (autoScrollEnabled.value) {
      scrollToBottom();
    }
  });
  
  // 触发生成单元测试
  setTimeout(() => {
    window?.vscode.postMessage({ 
      messageType: 'generateUnitTest',
      data: {
        mode: 'agent',
        filePath: data.filePath,
        isWholeFile: data.isWholeFile,
        selectedText: data.selectedText
      }
    });
  }, 500);
};

// 启动Fuzz测试生成时设置标志
</script>

<style scoped>
.containner {
  min-width: 320px;
  display: flex;
  flex-direction: column;
  width: 100%;
  height: 100vh;

  .header-wrapper {
    padding: 12px 16px;
  }

  .conversation-area,
  .welcome-page {
    flex: 1;
    display: flex;
    flex-direction: column;
    overflow: auto;
    padding: 20px 12px;
  }

  .conversation-area {
    gap: 8px;
    scrollbar-gutter: stable;

  }

  .conversation-area,
  .welcome-page {
    scrollbar-width: thin;  /* 可选值：auto | thin | none */
  }

  .welcome-page {
    gap: 24px;
    justify-content: center;
  }

  .guess-question {
    width: 100%;
    padding: 16px 12px;
    border-radius: var(--devui-border-radius-card);
    background-color: var(--devui-gray-form-control-bg);

    .guess-title {
      display: flex;
      justify-content: space-between;
      align-items: center;
      color: var(--devui-text);
      margin-bottom: 12px;

      &>div:first-child {
        font-weight: 700;
        font-size: var(--devui-font-size);
      }

      &>div:last-child {
        font-size: var(--devui-font-size-sm);
        cursor: pointer;

        span {
          margin-left: 4px;
        }
      }
    }

    .guess-content {
      display: flex;
      align-items: center;
      flex-wrap: wrap;
      gap: 8px;

      span {
        font-size: var(--devui-font-size-sm);
        color: var(--devui-text);
        padding: 4px 12px;
        border-radius: var(--devui-border-radius-full);
        background-color: var(--devui-gray-form-control-hover-bg);
        cursor: pointer;
      }
    }
  }

  .bubble-bottom-operations {
    margin-top: 8px;

    i {
      padding: 4px;
      border-radius: 4px;
      cursor: pointer;

      &:hover {
        background-color: var(--devui-icon-hover-bg);
      }
    }
  }

  .new-convo-button {
    padding: 0 12px;
    display: flex;
    justify-content: space-between;
    align-items: center;
    height: 39px;
    gap: 4px;
  }

  :deep(.simple-prompt .mc-list) {
    justify-content: unset;
  }

  :deep(.intro-prompt .mc-list) {
    justify-content: center;
  }

  .operations {
    i {
      padding: 4px;
      border-radius: 4px;
      cursor: pointer;

      &:hover {
        background: var(--devui-global-bg);
      }
    }
  }

  .agent-knowledge {
    display: flex;
    align-items: center;

    .agent-wrapper {
      display: flex;
      align-items: center;
      padding: 4px 8px;
      border-radius: var(--devui-border-radius-full);
      background-color: var(--devui-area);
      cursor: pointer;

      img {
        width: 16px;
        height: 16px;
        margin-right: 4px;
      }

      span {
        font-size: var(--devui-font-size);
        color: var(--devui-text);
        margin-right: 8px;
      }

      i {
        font-size: var(--devui-font-size);
        color: var(--devui-text);
        transition: transform 0.3s ease-in-out;

        &:last-child {
          margin-left: 4px;
        }
      }

      .is-open {
        transform: rotate(180deg);
      }
    }

    .agent-knowledge-dividing-line {
      width: 1px;
      height: 14px;
      margin: 0 12px;
      background-color: var(--devui-line);
    }

    .knowledge-wrapper {
      font-size: var(--devui-font-size);
      color: var(--devui-text);
      cursor: pointer;

      span {
        margin-left: 4px;
      }
    }
  }

  .input-foot-wrapper {
    display: flex;
    justify-content: space-between;
    align-items: center;
    width: 100%;
    height: 100%;
    margin-right: 8px;

    .input-foot-left {
      display: flex;
      align-items: center;
      gap: 8px;

      span {
        font-size: var(--devui-font-size-sm);
        color: var(--devui-text);
        cursor: pointer;
      }


      .input-foot-maxlength {
        font-size: var(--devui-font-size-sm);
        color: var(--devui-aide-text);
      }
    }

    .input-foot-right {
      &>*:not(:first-child) {
        margin-left: 8px;
      }
    }
  }
   .success-icon {
    color: #5CB300;
   }
  .headerIcon :deep(.mc-header-logo) {
    height: 32px;
    width: 32px;
  }

  :deep(.headerIcon2x) {
    img {
      height: 64px;
      width: 64px;
    }
  }



}

.input-foot-left {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: var(--devui-font-size-sm);
  color: var(--devui-text);

  i {
    margin-right: 4px;
  }
}

.appendix-wrap {
  display: flex;
  padding: 4px 8px;

  .appendix-item {
    padding: 4px;
    border-radius: var(--devui-border-radius);
    background-color: var(--devui-area);

    i {
      margin-left: 10px;
      cursor: pointer;
    }
  }
}

:deep(.mc-code-block-dark) pre code.hljs,
:deep(.mc-code-block-light) pre code.hljs{
    scrollbar-width: thin;
}

.auth-checking-container {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100vh;
  flex-direction: column;
  text-align: center;
  background-color: var(--devui-global-bg);
}

.auth-checking-box {
  padding: 3rem;
  border-radius: 12px;
  width: 80%;
  max-width: 450px;
  background-color: var(--devui-area);
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}

.loading-indicator {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  margin-top: 2rem;
  color: var(--devui-text);
  font-size: var(--devui-font-size);
}

.loading-indicator i {
  font-size: 1.2rem;
  animation: spin 1s linear infinite;
}

@keyframes spin {
  0% { transform: rotate(0deg); }
  100% { transform: rotate(360deg); }
}

.login-container {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100vh;
  flex-direction: column;
  text-align: center;
  background-color: var(--devui-global-bg);
}

.login-box {
  padding: 3rem;
  border-radius: 12px;
  width: 80%;
  max-width: 450px;
  background-color: var(--devui-area);
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}

.login-prompt {
  margin: 2rem 0;
}

.login-prompt p {
  color: var(--devui-text);
  font-size: var(--devui-font-size);
  margin-bottom: 1.5rem;
  line-height: 1.5;
}

.login-actions {
  display: flex;
  gap: 12px;
  justify-content: center;
  flex-wrap: wrap;
}

.login-actions :deep(.d-button[loading]) {
  cursor: wait;
}

.login-actions :deep(.d-button:disabled) {
  opacity: 0.6;
}

.login-form {
  margin-top: 1.5rem;
  padding-top: 1.5rem;
  border-top: 1px solid var(--devui-line);
}

.file-info-container {
  margin-top: 12px;
  padding: 12px;
  background-color: var(--devui-global-bg, #f3f6f8);
  border-radius: 4px;
  border-left: 3px solid var(--devui-success, #50d4ab);
}

.file-info-path {
  font-family: 'Consolas', 'Courier New', monospace;
  font-size: 13px;
  color: var(--devui-text, #252b3a);
  margin-bottom: 8px;
  padding: 4px 8px;
  background-color: var(--devui-base-bg, #ffffff);
  border-radius: 2px;
  word-break: break-all;
}

.file-info-buttons {
  display: flex;
  gap: 8px;
  justify-content: flex-start;
}

.file-action-container {
  margin-top: 12px;
  padding: 12px;
  background-color: var(--devui-global-bg, #f3f6f8);
  border-radius: 4px;
  border-left: 3px solid var(--devui-brand, #5e7ce0);
}

.file-action-path {
  font-family: 'Consolas', 'Courier New', monospace;
  font-size: 13px;
  color: var(--devui-text, #252b3a);
  margin-bottom: 8px;
  padding: 4px 8px;
  background-color: var(--devui-base-bg, #ffffff);
  border-radius: 2px;
  word-break: break-all;
}

.file-action-buttons {
  display: flex;
  gap: 8px;
  justify-content: flex-start;
  flex-wrap: wrap;
}

.login-form :deep(.d-input) {
  margin-bottom: 12px;
}

/* ========================================
   🎨 控制按钮组样式
   ======================================== */
.control-buttons-group {
  display: flex;
  gap: 8px;
  align-items: center;
  animation: fadeInSlide 0.3s ease-out;
}

@keyframes fadeInSlide {
  from {
    opacity: 0;
    transform: translateY(-5px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

.control-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 14px;
  border: none;
  border-radius: 8px;
  font-size: 13px;
  font-weight: 500;
  cursor: pointer;
  transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
  position: relative;
  overflow: hidden;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}

.control-btn:hover {
  transform: translateY(-1px);
  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15);
}

.control-btn:active {
  transform: translateY(0);
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}

.control-btn::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: linear-gradient(135deg, rgba(255, 255, 255, 0.2) 0%, rgba(255, 255, 255, 0) 100%);
  opacity: 0;
  transition: opacity 0.2s;
}

.control-btn:hover::before {
  opacity: 1;
}

.btn-icon {
  width: 16px;
  height: 16px;
  flex-shrink: 0;
  transition: transform 0.2s;
}

.control-btn:hover .btn-icon {
  transform: scale(1.1);
}

.btn-text {
  line-height: 1;
  white-space: nowrap;
}

/* 暂停按钮 - 橙黄色渐变 */
.pause-btn {
  background: linear-gradient(135deg, #ffa726 0%, #ff9800 100%);
  color: #fff;
  border: 1px solid rgba(255, 152, 0, 0.3);
}

.pause-btn:hover {
  background: linear-gradient(135deg, #fb8c00 0%, #f57c00 100%);
  box-shadow: 0 4px 12px rgba(255, 152, 0, 0.4);
}

.pause-btn .btn-icon {
  animation: pulse 1.5s ease-in-out infinite;
}

@keyframes pulse {
  0%, 100% {
    opacity: 1;
  }
  50% {
    opacity: 0.7;
  }
}

/* 继续按钮 - 绿色渐变 */
.resume-btn {
  background: linear-gradient(135deg, #66bb6a 0%, #4caf50 100%);
  color: #fff;
  border: 1px solid rgba(76, 175, 80, 0.3);
  animation: bounceIn 0.4s ease-out;
}

.resume-btn:hover {
  background: linear-gradient(135deg, #43a047 0%, #388e3c 100%);
  box-shadow: 0 4px 12px rgba(76, 175, 80, 0.4);
}

.resume-btn .btn-icon {
  animation: playIconBounce 0.6s ease-in-out;
}

@keyframes bounceIn {
  0% {
    transform: scale(0.8);
    opacity: 0;
  }
  50% {
    transform: scale(1.05);
  }
  100% {
    transform: scale(1);
    opacity: 1;
  }
}

@keyframes playIconBounce {
  0%, 100% {
    transform: translateX(0);
  }
  50% {
    transform: translateX(2px);
  }
}

/* 取消按钮 - 红色渐变 */
.cancel-btn {
  background: linear-gradient(135deg, #ef5350 0%, #e53935 100%);
  color: #fff;
  border: 1px solid rgba(229, 57, 53, 0.3);
}

.cancel-btn:hover {
  background: linear-gradient(135deg, #d32f2f 0%, #c62828 100%);
  box-shadow: 0 4px 12px rgba(229, 57, 53, 0.4);
}

.cancel-btn:hover .btn-icon {
  animation: shake 0.4s ease-in-out;
}

/* 清屏按钮样式（新增）*/
.clear-btn {
  background: linear-gradient(135deg, #78909c 0%, #607d8b 100%);
  color: #fff;
  border: 1px solid rgba(96, 125, 139, 0.3);
}

.clear-btn:hover {
  background: linear-gradient(135deg, #546e7a 0%, #455a64 100%);
  box-shadow: 0 4px 12px rgba(96, 125, 139, 0.4);
}

.clear-btn:hover .btn-icon {
  animation: fadeOut 0.4s ease-in-out;
}

@keyframes shake {
  0%, 100% {
    transform: rotate(0deg);
  }
  25% {
    transform: rotate(-10deg);
  }
  75% {
    transform: rotate(10deg);
  }
}

@keyframes fadeOut {
  0%, 100% {
    opacity: 1;
  }
  50% {
    opacity: 0.5;
  }
}

/* 暗色主题适配 */
@media (prefers-color-scheme: dark) {
  .control-btn {
    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
  }
  
  .control-btn:hover {
    box-shadow: 0 4px 8px rgba(0, 0, 0, 0.4);
  }
  
  .pause-btn:hover {
    box-shadow: 0 4px 12px rgba(255, 152, 0, 0.5);
  }
  
  .resume-btn:hover {
    box-shadow: 0 4px 12px rgba(76, 175, 80, 0.5);
  }
  
  .cancel-btn:hover {
    box-shadow: 0 4px 12px rgba(229, 57, 53, 0.5);
  }
  
  .clear-btn:hover {
    box-shadow: 0 4px 12px rgba(96, 125, 139, 0.5);
  }
}

/* 响应式设计 - 小屏幕（侧边栏较窄时隐藏文字）*/
@media (max-width: 480px) {
  .control-buttons-group {
    gap: 6px;
  }
  
  .control-btn {
    padding: 5px 10px;
    font-size: 12px;
  }
  
  .btn-icon {
    width: 14px;
    height: 14px;
  }
  
  .btn-text {
    display: none;  /* 小屏幕隐藏文字，仅显示图标 */
  }
}
</style>